package cn.hchaojie.camp.day13;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils.Collections;

public class DemoProducerAndConsumer {
	public static void main(String[] args) {
		ExecutorService service = Executors.newFixedThreadPool(10);
		
		Factory factory = new Factory();

		service.execute(new Producer(factory));
		service.execute(new Consumer(factory));
		
		service.shutdown();
	}
}

class Producer implements Runnable {
	private Factory factory;
	public Producer(Factory f) {
		this.factory = f;
	}
	
	@Override
	public void run() {
		// 不断的生产egg

		try {
			while (true) {
				// 往工厂里面放入一个产品
				factory.put();
				
				Thread.sleep((long) (Math.random() * 10));
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

class Consumer implements Runnable {
	private Factory f;
	public Consumer(Factory f) {
		this.f = f;
	}

	@Override
	public void run() {
		try {
			while (true) {
				f.buy();
				
				Thread.sleep((long) (Math.random() * 10));
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

class Factory {
	private static final int MAX = 10;
	List<Integer> eggs = new ArrayList<>();
	
	int id = 1;
	
	// synchorized 给对象加上了锁, 同时只有一个线程可以访问对象的方法
	
	// 消费一个产品
	public synchronized void buy() {
		if (eggs.size() == 0) {
			System.out.println("鸡蛋卖完了。。。白跑一趟。。。");
			
			try {
				wait();	// 让当前的线程处于等待状态。并且释放了当前对象的锁
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		if (eggs.size() == 0) return;	// 双重检查
		
		Integer last = eggs.remove(eggs.size() - 1);
		System.out.println("买到了一个鸡蛋。。。# " + last);	

		notify();
	}
	
	// 生产一个产品
	public synchronized void put() {
		if (eggs.size() >= MAX) {
			System.out.println("MD, 放不下了。。。鸡蛋扔掉吧。。");
			try {
				System.out.println("等等吧。总会有人买走鸡蛋的。。。");
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		System.out.println("放入了一个鸡蛋。。。#" + id);
		eggs.add(id++);
		
		notify();		// 唤醒其它处于等待的线程
	}
}
